use crate::errors::MyError;
use crate::models::NoteCategory;
use crate::utils::{gen_uuid, is_not_empty_or, to_now_ticks};
use async_recursion::async_recursion;
use deadpool_postgres::Client;
use std::result::Result;

async fn create_or_update_note_category(
    note_category: &NoteCategory,
    client: &Client,
) -> Result<String, MyError> {
    let id: String = if note_category.id.is_empty() {
        gen_uuid()
    } else {
        note_category.id.clone()
    };

    if note_category.id.is_empty() {
        let _ = client
            .execute(
                "insert into note_categories(id, title, created_date, parent_id) values($1, $2, $3, $4);",
                &[&id, &note_category.title, &(to_now_ticks()? as i64), &is_not_empty_or(&note_category.parent_id, "null")]
            )
            .await?;
    } else {
        let _ = client
            .execute(
                "update note_category set title=$2, parent_id=$3 where id=$1",
                &[
                    &id,
                    &note_category.title,
                    &is_not_empty_or(&note_category.parent_id, "null"),
                ],
            )
            .await?;
    }
    Ok(id)
}
#[async_recursion]
async fn update_note_category(
    note_category: &NoteCategory,
    client: &Client,
    id_seq: &mut Vec<String>,
) -> Result<(), MyError> {
    let id = create_or_update_note_category(note_category, client).await?;
    id_seq.push(id.to_owned());
    for child_category in &note_category.children {
        update_note_category(child_category.to_owned().parent_id(&id), client, id_seq).await?;
    }
    Ok(())
}

pub async fn insert_or_update_note_category(
    note: &NoteCategory,
    client: &Client,
) -> Result<String, MyError> {
    // 如果没有id，创建数据
    // 如果有id，更新数据
    // 如果要删除有id的数据，iijjkkjjggkkkkkk需要先判断是否有关联数据

    let note1 = &mut note.to_owned();
    let id_seq = &mut Vec::<String>::new();
    update_note_category(note1, client, id_seq).await?;

    let id = id_seq
        .first()
        .ok_or_else(|| MyError::Msg("根分类Id不存在".to_owned()))?;

    Ok(id.to_owned())
}

pub async fn delete_category(id: &str, client: &Client) -> Result<(), MyError> {
    let _ = client
        .execute("delete from note_categories where id=$1", &[&id])
        .await?;

    Ok(())
}

#[async_recursion]
async fn get_category_recursive(id: &str, client: &Client) -> Result<NoteCategory, MyError> {
    let result = client
        .query(
            "select id, parent_id, title, created_date from note_categories where id=$1",
            &[&id],
        )
        .await?
        .iter()
        .map(|row| NoteCategory {
            id: "0".into(),
            title: row.get("title"),
            parent_id: row.get("parent_id"),
            created_date: row.get("created_date"),
            children: Vec::<NoteCategory>::new(),
        })
        .collect::<Vec<NoteCategory>>();
    let category = &mut result
        .first()
        .ok_or(MyError::Msg(format!("NoteCategory id:{},数据不存在", id)))?
        .to_owned();

    // 获取children
    let children_ids = client
        .query("select id from note_categories where parent_id=$1", &[&id])
        .await?
        .iter()
        .map(|row| row.get("id"))
        .collect::<Vec<String>>();

    for child_id in &children_ids {
        category
            .children
            .push(get_category_recursive(child_id, client).await?);
    }
    Ok((*category).clone())
}
pub async fn get_category_with_children(
    id: &str,
    client: &Client,
) -> Result<NoteCategory, MyError> {
    get_category_recursive(id, client).await
}
